package club.bigtian.mf.plugin.core.generator;

import cn.hutool.core.util.StrUtil;
import com.intellij.codeInsight.completion.InsertionContext;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.searches.ClassInheritorsSearch;

import java.util.List;
import java.util.Map;

/**
 * Service方法生成器
 * 负责在接口和实现类中生成方法
 */
public class ServiceMethodGenerator {

    private final ImportManager importManager;

    public ServiceMethodGenerator() {
        this.importManager = new ImportManager();
    }

    /**
     * 获取ImportManager实例
     */
    public ImportManager getImportManager() {
        return importManager;
    }

    /**
     * 在Service接口和实现类中生成方法
     */
    public void generateServiceMethodInInterfaceAndImpl(InsertionContext context, PsiClass serviceInterface,
                                                       String methodName, String methodBody, String returnType,
                                                       String fieldsCompletion, Map<String, FieldInfo> entityFields,
                                                       String entityQualifiedName, Map<String, String> fieldToTableDefMapping) {
        
        System.out.println("ServiceMethodGenerator: generateServiceMethodInInterfaceAndImpl called");
        System.out.println("  methodName: " + methodName);
        System.out.println("  returnType: " + returnType);
        System.out.println("  serviceInterface: " + (serviceInterface != null ? serviceInterface.getName() : "null"));

        ApplicationManager.getApplication().runWriteAction(() -> {
            try {
                Project project = context.getProject();

                // 确保文档已提交
                PsiDocumentManager.getInstance(project).commitAllDocuments();

                // 1. 先替换用户输入为方法调用，避免影响接口方法声明的添加
                replaceUserInput(context, methodName);

                // 2. 生成参数列表
                String parameters = generateParameters(fieldsCompletion, entityFields, entityQualifiedName, fieldToTableDefMapping);

                // 3. 在接口中生成方法声明
                generateInterfaceMethod(serviceInterface, methodName, returnType, parameters, fieldsCompletion, entityFields, entityQualifiedName, project);

                // 4. 在实现类中生成方法实现
                generateImplementationMethodAsync(project, serviceInterface, methodName, returnType, parameters, methodBody, fieldsCompletion, entityFields, entityQualifiedName);

                // 5. 将光标定位到括号内
                positionCursor(context, methodName);

            } catch (Exception e) {
                System.err.println("Error generating service method: " + e.getMessage());
                e.printStackTrace();
            }
        });
    }

    /**
     * 替换用户输入
     */
    private void replaceUserInput(InsertionContext context, String methodName) {
        com.intellij.openapi.editor.Document document = context.getDocument();
        int startOffset = context.getStartOffset();
        int tailOffset = context.getTailOffset();

        String userInputReplacement = methodName + "()";
        document.replaceString(startOffset, tailOffset, userInputReplacement);

        // 提交文档更改，确保PSI同步
        PsiDocumentManager.getInstance(context.getProject()).commitDocument(document);
    }

    /**
     * 生成参数列表
     */
    private String generateParameters(String fieldsCompletion, Map<String, FieldInfo> entityFields, 
                                    String entityQualifiedName, Map<String, String> fieldToTableDefMapping) {
        StringBuilder paramBuilder = new StringBuilder();

        // 检查是否是整个实体方法
        if ("Entity".equals(fieldsCompletion) || "EntityLike".equals(fieldsCompletion)) {
            String simpleEntityName = StrUtil.subAfter(entityQualifiedName, ".", true);
            paramBuilder.append(simpleEntityName).append(" ").append(StrUtil.lowerFirst(simpleEntityName));
        } else {
            // 普通字段方法，解析字段生成参数
            List<String> fields = parseFieldsFromCompletion(fieldsCompletion);
            boolean firstParam = true;
            for (String field : fields) {
                FieldInfo fieldInfo = entityFields.get(field);
                if (fieldInfo != null && fieldToTableDefMapping.containsKey(field)) {
                    if (!firstParam) paramBuilder.append(", ");
                    paramBuilder.append(fieldInfo.fieldType).append(" ").append(fieldInfo.fieldName);
                    firstParam = false;
                }
            }
        }

        return paramBuilder.toString();
    }

    /**
     * 在接口中生成方法声明
     */
    private void generateInterfaceMethod(PsiClass serviceInterface, String methodName, String returnType, 
                                       String parameters, String fieldsCompletion, Map<String, FieldInfo> entityFields,
                                       String entityQualifiedName, Project project) {
        try {
            PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);

            // 创建纯粹的方法声明
            String methodDeclaration = returnType + " " + methodName + "(" + parameters + ");";
            PsiMethod interfaceMethod = factory.createMethodFromText(methodDeclaration, serviceInterface);

            // 添加方法到接口
            PsiMethod addedMethod = (PsiMethod) serviceInterface.add(interfaceMethod);

            System.out.println("Successfully added method to interface: " + addedMethod.getName());
            System.out.println("Interface method text: " + addedMethod.getText());
            System.out.println("Interface class: " + serviceInterface.getName());
            System.out.println("Interface file: " + serviceInterface.getContainingFile().getName());

            // 添加JavaDoc注释到接口方法
            try {
                addJavaDocToMethod(addedMethod, methodName, fieldsCompletion, entityFields, entityQualifiedName, factory);
            } catch (Exception e) {
                System.err.println("Failed to add JavaDoc to interface method: " + e.getMessage());
            }

        } catch (Exception e) {
            System.err.println("Error generating interface method: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 异步在实现类中生成方法实现
     */
    private void generateImplementationMethodAsync(Project project, PsiClass serviceInterface, String methodName,
                                                 String returnType, String parameters, String methodBody,
                                                 String fieldsCompletion, Map<String, FieldInfo> entityFields, String entityQualifiedName) {
        // 在读取操作中获取必要信息
        ApplicationManager.getApplication().runReadAction(() -> {
            try {
                // 查找实现类
                PsiClass serviceImpl = findServiceImplementation(serviceInterface, project);
                if (serviceImpl == null) {
                    System.err.println("Service implementation not found for interface: " + serviceInterface.getQualifiedName());
                    return;
                }

                System.out.println("Found service implementation: " + serviceImpl.getQualifiedName());

                // 在EDT线程中执行写入操作
                ApplicationManager.getApplication().invokeLater(() -> {
                    WriteCommandAction.runWriteCommandAction(project, () -> {
                        try {
                            generateImplementationMethod(serviceImpl, methodName, returnType, parameters, methodBody, fieldsCompletion, entityFields, entityQualifiedName, project);
                        } catch (Exception e) {
                            System.err.println("Error generating method implementation: " + e.getMessage());
                            e.printStackTrace();
                        }
                    });
                });

            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }

    /**
     * 生成实现类方法
     */
    private void generateImplementationMethod(PsiClass serviceImpl, String methodName, String returnType, 
                                            String parameters, String methodBody, String fieldsCompletion,
                                            Map<String, FieldInfo> entityFields, String entityQualifiedName, Project project) {
        try {
            // 确保文档已提交
            PsiDocumentManager.getInstance(project).commitAllDocuments();

            PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);

            // 生成方法实现
            String methodText = "@Override\n" +
                              "public " + returnType + " " + methodName + "(" + parameters + ") {\n" +
                              "    " + methodBody.replace("\n", "\n    ") + "\n" +
                              "}";

            System.out.println("Generated method text: " + methodText);

            PsiMethod method = factory.createMethodFromText(methodText, serviceImpl);

            // 在实现类中插入方法
            PsiMethod addedMethod = (PsiMethod) serviceImpl.add(method);

            System.out.println("Successfully added method to implementation: " + addedMethod.getName());
            System.out.println("Implementation method text: " + addedMethod.getText());
            System.out.println("Implementation class: " + serviceImpl.getName());
            System.out.println("Implementation file: " + serviceImpl.getContainingFile().getName());

            // 添加JavaDoc注释到实现方法
            addJavaDocToMethod(addedMethod, methodName, fieldsCompletion, entityFields, entityQualifiedName, factory);

            // 添加必要的导入语句
            importManager.addRequiredImportsToFile(serviceImpl.getContainingFile(), methodBody, project);

        } catch (Exception e) {
            System.err.println("Error generating method implementation: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 查找Service实现类
     */
    private PsiClass findServiceImplementation(PsiClass serviceInterface, Project project) {
        try {
            if (serviceInterface == null || !serviceInterface.isInterface()) {
                return null;
            }

            GlobalSearchScope scope = GlobalSearchScope.allScope(project);

            // 查找直接实现该接口的类
            for (PsiClass implementor : ClassInheritorsSearch.search(serviceInterface, scope, false)) {
                if (!implementor.isInterface() && !implementor.hasModifierProperty(PsiModifier.ABSTRACT)) {
                    return implementor;
                }
            }

        } catch (Exception e) {
            System.err.println("Error searching for implementation: " + e.getMessage());
        }
        return null;
    }

    /**
     * 定位光标
     */
    private void positionCursor(InsertionContext context, String methodName) {
        int startOffset = context.getStartOffset();
        int cursorPosition = startOffset + methodName.length() + 1; // +1 for opening parenthesis
        context.getEditor().getCaretModel().moveToOffset(cursorPosition);
    }

    // 临时方法，后续需要从其他类中提取
    private List<String> parseFieldsFromCompletion(String fieldsCompletion) {
        // 简单的解析逻辑：按And/Or分割
        List<String> fields = new ArrayList<>();
        if (StrUtil.isEmpty(fieldsCompletion)) {
            return fields;
        }

        String[] parts = fieldsCompletion.split("(?=And|Or)");
        for (String part : parts) {
            // 移除And/Or前缀
            String fieldPart = part;
            if (fieldPart.startsWith("And")) {
                fieldPart = fieldPart.substring(3);
            } else if (fieldPart.startsWith("Or")) {
                fieldPart = fieldPart.substring(2);
            }

            // 移除查询类型后缀
            String[] suffixes = {"Like", "Gt", "Lt", "Ge", "Le", "Ne", "In", "NotIn", "Between", "NotBetween", "IsNull", "IsNotNull"};
            for (String suffix : suffixes) {
                if (fieldPart.endsWith(suffix)) {
                    fieldPart = fieldPart.substring(0, fieldPart.length() - suffix.length());
                    break;
                }
            }

            if (StrUtil.isNotEmpty(fieldPart)) {
                fields.add(fieldPart);
            }
        }
        return fields;
    }

    private void addJavaDocToMethod(PsiMethod method, String methodName, String fieldsCompletion,
                                  Map<String, FieldInfo> entityFields, String entityQualifiedName, PsiElementFactory factory) {
        try {
            // 生成简单的JavaDoc注释
            String description = generateMethodDescription(methodName);
            String commentText = "/**\n     * " + description + "\n     */";

            PsiDocComment docComment = factory.createDocCommentFromText(commentText);
            if (method.getDocComment() == null) {
                method.addBefore(docComment, method.getFirstChild());
            }
        } catch (Exception e) {
            System.err.println("Failed to add JavaDoc: " + e.getMessage());
        }
    }

    private String generateMethodDescription(String methodName) {
        String lowerMethodName = methodName.toLowerCase();
        if (lowerMethodName.startsWith("listby")) {
            return "根据条件查询列表";
        } else if (lowerMethodName.startsWith("findby")) {
            return "根据条件查找数据";
        } else if (lowerMethodName.startsWith("getby")) {
            return "根据条件获取单个数据";
        } else if (lowerMethodName.startsWith("countby")) {
            return "根据条件统计数量";
        } else if (lowerMethodName.startsWith("existsby")) {
            return "根据条件检查是否存在";
        } else if (lowerMethodName.startsWith("removeby") || lowerMethodName.startsWith("deleteby")) {
            return "根据条件删除数据";
        } else {
            return "根据条件查询数据";
        }
    }

    /**
     * 字段信息类
     */
    public static class FieldInfo {
        public String fieldName;
        public String fieldType;
        public String columnName;

        public FieldInfo(String fieldName, String fieldType, String columnName) {
            this.fieldName = fieldName;
            this.fieldType = fieldType;
            this.columnName = columnName;
        }
    }
}
